package com.mxpio.erp.plm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectReader;
import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.enums.PlmEnums;
import com.mxpio.erp.common.enums.ProjectTaskEnums;
import com.mxpio.erp.common.plm.bo.ProjectTaskBO;
import com.mxpio.erp.common.plm.entity.*;
import com.mxpio.erp.common.plm.service.*;
import com.mxpio.erp.common.plm.vo.ProjectTaskVO;
import com.mxpioframework.camunda.service.BpmnFlowService;
import com.mxpioframework.common.exception.MBootException;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.jpa.query.SimpleCriterion;
import com.mxpioframework.message.service.MessageService;
import com.mxpioframework.security.util.SecurityUtils;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 *  项目任务列表接口
 *  @author mxpio
 *  @since 2020/7/29 10:13
 */
@Service
@Slf4j
public class ProjectTaskServiceImpl extends BaseServiceImpl<ProjectTask> implements ProjectTaskService {

    @Autowired
    private BpmnFlowService bpmnFlowService;
    @Resource
    private MessageService messageService;//消息

    @Autowired
    private ProjectTaskStatusHistoryService projectTaskStatusHistoryService;

    @Autowired
    private ProjectTaskExecutionLogService projectTaskExecutionLogService;

    @Autowired
    private ProjectInfoService projectInfoService;
    @Autowired
    private ProjectTaskDeliverableService projectTaskDeliverableService;
    @Autowired
    private ProjectTaskDeliverableDraftService projectTaskDeliverableDraftService;
    @Autowired
    private ProjectTaskCompleteService projectTaskCompleteService;
    @Autowired
    private ProjectTaskCompleteDeliverableDraftService projectTaskCompleteDeliverableDraftService;
    @Autowired
    private ProjectTaskMembersTimeService projectTaskMembersTimeService;
    @Autowired
    private ProjectTaskAuditRecordsService projectTaskAuditRecordsService;
    @Autowired
    private ProjectTaskEndDeliverableDraftService projectTaskEndDeliverableDraftService;

    public static final String[] channelCodes = {"innerMsg"};




    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> getSameLevelTasks(String proCode, String parentTaskCode) {
        List<ProjectTask> tasks;
        if(StrUtil.isEmpty(parentTaskCode)){
            tasks = JpaUtil.linq(ProjectTask.class)
                    .equal("proCode", proCode)
                    .isNull("parentTaskCode")
                    .asc("number")
                    .list();
        }else {
            tasks = JpaUtil.linq(ProjectTask.class)
                    .equal("proCode", proCode)
                    .equal("parentTaskCode", parentTaskCode)
                    .asc("number")
                    .list();
        }
        return tasks;
    }

    /**
     * 获取所有子任务
     */
    @Override
    @Transactional(readOnly = true)
    public List<ProjectTask> getChildrenTasks(String proCode, String parentTaskCode) {
        // 获取当前项目下的所有任务
        List<ProjectTask> allTasks = JpaUtil.linq(ProjectTask.class).equal("proCode", proCode).list();

        // 初始化用于收集所有子任务的平铺列表
        List<ProjectTask> flatChildrenList = new ArrayList<>();

        // 填充子任务列表
        findAllChildren(allTasks, parentTaskCode, flatChildrenList);

        return flatChildrenList;
    }

    private Criteria dealWithTaskName(Criteria criteria){
        if(criteria == null || CollectionUtil.isEmpty(criteria.getCriterions())){
            return criteria;
        }
        Criteria c = Criteria.create();
        String taskName = "";
        for(Object obj : criteria.getCriterions()){
            if(obj instanceof SimpleCriterion){
                SimpleCriterion simpleCriterion = (SimpleCriterion) obj;
                if("taskName".equals(simpleCriterion.getFieldName())){
                    taskName = (String) simpleCriterion.getValue();
                }else {
                    c.addCriterion(obj);
                }
            }else {
                c.addCriterion(obj);
            }
        }
        if(StrUtil.isNotEmpty(taskName)){
            Criteria c1 = Criteria.create();
            c1.addCriterion("taskName", Operator.LIKE, taskName);
            List<ProjectTask> list = this.list(ProjectTask.class, c1);
            List<String> taskCodes = list.stream().map(ProjectTask::getTaskCode).collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(taskCodes)){
                c.addCriterion("taskCode", Operator.IN, taskCodes);
            }
        }
        return c;
    }

    @Override
    @Transactional(readOnly = true)
    public Page<ProjectTaskVO> pageApproval(Pageable page, Criteria c) {
        Page<ProjectTaskExecutionLog> taskExecutionLogPage = projectTaskExecutionLogService.listPage(ProjectTaskExecutionLog.class, page, dealWithTaskName(c));
        List<ProjectTaskExecutionLog> logsContent = taskExecutionLogPage.getContent();
        List<String> taskCodes = logsContent.stream().map(ProjectTaskExecutionLog::getTaskCode).collect(Collectors.toList());
        List<ProjectTask> tasks = JpaUtil.linq(ProjectTask.class).in("taskCode", taskCodes).list();
        Map<String, ProjectTask> collect = tasks.stream().collect(Collectors.toMap(ProjectTask::getTaskCode, task -> task));
        ArrayList<ProjectTaskVO> projectTaskVOS = new ArrayList<>();
        for(ProjectTaskExecutionLog log : logsContent){
            ProjectTask projectTask = collect.get(log.getTaskCode());
            if(projectTask != null){
                if (log.getIsAuditEnd()==null){
                    ProjectTaskVO projectTaskVO = new ProjectTaskVO();
                    BeanUtil.copyProperties(projectTask, projectTaskVO);
                    projectTaskVO.setTaskLogId(log.getId());
                    projectTaskVO.setLogType(log.getLogType());
                    projectTaskVO.setAuditStatus(log.getAuditStatus());
                    projectTaskVO.setAuditOpinion(log.getAuditOpinion());
                    projectTaskVO.setProName(projectTask.getProName());
                    projectTaskVO.setProLeader(projectTask.getProLeader());
                    projectTaskVO.setProStatus(projectTask.getProStatus());
                    projectTaskVO.setApplyDesc(log.getApplyDesc());
                    projectTaskVO.setActualStartTime(log.getActualStartTime());
                    projectTaskVO.setActualEndTime(log.getActualEndTime());
                    projectTaskVO.setActualDuration(log.getActualDuration()!=null ?log.getActualDuration():null);//实际工期
                    projectTaskVO.setNormalWorkTime(log.getNormalWorkTime()!=null ? log.getNormalWorkTime():null);//正常工时
                    projectTaskVO.setOvertimeWorkTime(log.getOvertimeWorkTime()!=null ? log.getOvertimeWorkTime():null );//加班工时
                    projectTaskVO.setApplyDesc(log.getApplyDesc()!=null ? log.getApplyDesc() : null);//说明
                    projectTaskVO.setCreateTime(projectTask.getCreateTime());
                    projectTaskVO.setApprovalPlan(log.getApprovalPlan());
                    projectTaskVO.setWorkflowId(log.getWorkflowId());
                    projectTaskVOS.add(projectTaskVO);
                }
            }
        }
        Collections.sort(projectTaskVOS, Comparator.comparing(ProjectTaskVO::getCreateTime).reversed()); // 降序排序
        return new PageImpl<>(projectTaskVOS, taskExecutionLogPage.getPageable(), taskExecutionLogPage.getTotalElements());
    }

    // 递归辅助方法，用于收集所有子任务到平铺列表中
    private void findAllChildren(List<ProjectTask> allTasks, String parentTaskCode, List<ProjectTask> flatChildrenList) {
        // 从所有任务中过滤出当前父任务代码下的直接子任务
        List<ProjectTask> children = allTasks.stream().filter(task ->
                (StrUtil.isEmpty(parentTaskCode) ? StrUtil.isEmpty(task.getParentTaskCode()) : parentTaskCode.equals(task.getParentTaskCode()))
        ).collect(Collectors.toList());

        // 将找到的子任务添加到平铺列表中
        flatChildrenList.addAll(children);

        // 对每个找到的子任务递归寻找其子任务，并添加到平铺列表中
        for (ProjectTask child : children) {
            findAllChildren(allTasks, child.getTaskCode(), flatChildrenList);
        }
    }

    /**
     * 检查是否存在循环依赖
     *
     * @param task 要检查的任务
     * @param beforeTaskCode 潜在的前置任务Code
     * @return 如果存在循环依赖，则为 true
     */
    public boolean checkForCircularDependency(ProjectTask task, String beforeTaskCode) {
        if (StrUtil.isEmpty(beforeTaskCode)) {
            return false;
        }
        if (beforeTaskCode.equals(task.getTaskCode())) {
            return true;
        }
        for (ProjectTask beforeTask : getBeforeTasks(beforeTaskCode)) {
            if (checkForCircularDependency(task, beforeTask.getTaskCode())) {
                return true;
            }
        }
        return false;
    }

    private List<ProjectTask> getBeforeTasks(String taskCode) {
        ProjectTask task = this.getById(ProjectTask.class, taskCode);
        if (task == null || StrUtil.isEmpty(task.getBeforeTask())) {
            return new ArrayList<>();
        }
        return JpaUtil.linq(ProjectTask.class).in("taskCode", Arrays.asList(task.getBeforeTask().split(";"))).list();
    }

    /**
     * 新增任务
     * @param projectTask
     * @return
     */
    @Override
    @Transactional
    public Result<?> saveTask(ProjectTask projectTask) {
        //任务计划开始和计划结束时间不要再项目计划和结束之间
        //获取任务模板的计划开始时间和计划结束时间
        Date planStartTime = projectTask.getPlanStartTime();
        Date planEndTime = projectTask.getPlanEndTime();
        String proCode = projectTask.getProCode();
        ProjectInfo one = JpaUtil.linq(ProjectInfo.class).equal("proCode", proCode).findOne();
        if (one.getProStatus().equals(PlmEnums.ProStatus.FINISH.getCode())|| one.getProStatus().equals(PlmEnums.ProStatus.END.getCode())){
            return Result.error("项目已结束，无法新增任务");
        }
        //获取项目计划开始时间和项目计划结束时间
        Date proPlanStartTime = one.getPlanStartTime();
        Date proPlanEndTime = one.getPlanEndTime();
        //判断任务计划开始时间和计划结束时间是否在项目计划和结束之间
        if (planStartTime.before(proPlanStartTime) || planStartTime.after(proPlanEndTime) || planEndTime.before(proPlanStartTime) || planEndTime.after(proPlanEndTime)){
            return Result.error("任务计划开始时间和计划结束时间必须在项目计划和结束时间之间" +"\n"+
                    "项目计划开始时间："+proPlanStartTime+"\n" +
                    "项目计划结束时间："+proPlanEndTime);
        }
        //为子级任务时，计划开始和结束需在父级时间内
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            //判断子级任务计划开始和结束时间是否在父级任务计划时间内
            if(parentTask.getPlanStartTime().after(planStartTime) || parentTask.getPlanEndTime().before(planEndTime)){
                return Result.error("子级任务计划开始和结束时间必须在父级任务计划时间内");
            }
        }
        //当前任务的前置任务与父级任务相等时，关联关系不能选择完成-开始，完成-完成
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
        if (StrUtil.equals(projectTask.getBeforeTask(), projectTask.getParentTaskCode())){
            if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())||
                projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                return Result.error("前置任务与父级任务相等时，关联关系不能选择完成-开始，完成-完成");
            }
        }
        }

        //当前任务的前置任务与根任务相等时，关联关系不能选择完成-开始，完成-完成
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())&& StrUtil.isNotEmpty(projectTask.getBeforeTask())) {
            List<String> strings = new ArrayList<>();
            String parentTaskCode = projectTask.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode,strings);
            for (String rootTaskCode : rootTaskCodes){
                if (projectTask.getBeforeTask().equals(rootTaskCode)){
                    if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())||
                            projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                        return Result.error("前置任务为父级任务时，关联关系不能选择完成-开始，完成-完成");
                    }
                }
            }
        }


        //校验父任务状态
        if(StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            if(parentTask.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())){
                return Result.error("父任务已完成，不能添加子任务");
            }
        }
        projectTask.setTaskStatus("1");
        projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode());
        // 获取序号
        projectTask.setNumber(getMaxNumberByParentTaskCode(projectTask.getProCode(), projectTask.getParentTaskCode()) + 1);
        //处理任务成员、负责人
        if (projectTask.getTaskMembers()!=null){
            projectTask.setTaskMembers(dealUserName(projectTask.getTaskMembers()));
        }
        projectTask.setHead(dealUserName(projectTask.getHead()));
        //添加对应的项目名称和项目状态和项目经理
        projectTask.setProName(one.getProName());
        projectTask.setProStatus(one.getProStatus());
        projectTask.setProLeader(one.getProLeader());

        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
        ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
        projectTask.setParentTaskName(parentTask.getTaskName());
        projectTask.setParentHead(parentTask.getHead());
        }
        //确定当前任务层级
        int level = 0;
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
            List<String> strings = new ArrayList<>();
            String parentTaskCode1 = projectTask.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode1,strings);
            level = rootTaskCodes.size();
            String strValue = Integer.toString(level);
            projectTask.setLevel(strValue+"级");

        }else {
            //如果当前任务没有父任务，则当前任务为根任务
            projectTask.setLevel("根任务");
        }
        projectTask.setOverdueDays("0");
        this.save(projectTask);

        //保存交付物
        List<ProjectTaskDeliverable> deliverables = projectTask.getDeliverables();
        if(CollectionUtil.isNotEmpty(deliverables)){
            deliverables.forEach(deliverable -> {
                deliverable.setTaskCode(projectTask.getTaskCode());
            });
            JpaUtil.save(deliverables);
        }
        return Result.OK(projectTask);
    }

    //取出当前任务的根任务
    private List<String> checkTask(String parentTaskCode, List<String> strings){
        //找到当前任务的父任务
        ProjectTask parentTask = this.getById(ProjectTask.class, parentTaskCode);
        //如果当前任务没有父任务，则当前任务为根任务
        if (StrUtil.isEmpty(parentTask.getParentTaskCode())){
            strings.add(parentTask.getTaskCode());
            return strings;
        }
        //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
        strings.add(parentTask.getTaskCode());
        String parentTaskCode1 = parentTask.getParentTaskCode();
        return checkTask(parentTaskCode1, strings);
    }


    /**
     * 编辑任务
     * @param projectTask
     * @return
     */
    @Override
    @Transactional
    public Result<?> editTask(ProjectTask projectTask) {
        //任务计划开始和计划结束时间不要再项目计划和结束之间
        //获取任务模板的计划开始时间和计划结束时间
        Date planStartTime = projectTask.getPlanStartTime();
        Date planEndTime = projectTask.getPlanEndTime();
        String proCode = projectTask.getProCode();
        ProjectInfo one = JpaUtil.linq(ProjectInfo.class).equal("proCode", proCode).findOne();
        //获取项目计划开始时间和项目计划结束时间
        Date proPlanStartTime = one.getPlanStartTime();
        Date proPlanEndTime = one.getPlanEndTime();
        //判断任务计划开始时间和计划结束时间是否在项目计划和结束之间
        if (planStartTime.before(proPlanStartTime) || planStartTime.after(proPlanEndTime) || planEndTime.before(proPlanStartTime) || planEndTime.after(proPlanEndTime)){
            return Result.error("任务计划开始时间和计划结束时间必须在项目计划和结束时间之间" +"\n"+
                    "项目计划开始时间："+proPlanStartTime+"\n" +
                    "项目计划结束时间："+proPlanEndTime);
        }

        //为子级任务时，计划开始和结束需在父级时间内
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            //判断子级任务计划开始和结束时间是否在父级任务计划时间内
            if(parentTask.getPlanStartTime().after(planStartTime) || parentTask.getPlanEndTime().before(planEndTime)){
                return Result.error("子级任务计划开始和结束时间必须在父级任务计划时间内");
            }
        }
        //当前任务的前置任务与父级任务相等时，关联关系不能选择完成-开始，完成-完成
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            if (StrUtil.equals(projectTask.getBeforeTask(), projectTask.getParentTaskCode())){
                if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())||
                        projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                    return Result.error("前置任务与父级任务相等时，关联关系不能选择完成-开始，完成-完成");
                }
            }
        }

        //当前任务的前置任务与根任务相等时，关联关系不能选择完成-开始，完成-完成
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())&& StrUtil.isNotEmpty(projectTask.getBeforeTask())) {
            List<String> strings = new ArrayList<>();
            String parentTaskCode = projectTask.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode,strings);
            for (String rootTaskCode : rootTaskCodes){
                if (projectTask.getBeforeTask().equals(rootTaskCode)){
                    if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())||
                            projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                        return Result.error("前置任务为父级任务时，关联关系不能选择完成-开始，完成-完成");
                    }
                }
            }
        }

        //对父类子类，进行死循环检验
        ProjectTask byId = this.getById(ProjectTask.class, projectTask.getTaskCode());
//        if(taskTemplate.getTaskCode().equals(taskTemplate.getParentTaskCode())){
//            return Result.error("自己不能为自己的父级");
//        }
        List<ProjectTask> childrenTasks = this.getChildrenTasks(byId.getProCode(), byId.getTaskCode());
        List<String> taskCodes = childrenTasks.stream().map(ProjectTask::getTaskCode).collect(Collectors.toList());
        for (String taskCode : taskCodes){
            if (taskCode.equals(projectTask.getParentTaskCode())){
                return Result.error("子级不能为父级的父级");
            }
        }
        //处理任务成员、负责人
        if (projectTask.getTaskMembers()!=null){
            projectTask.setTaskMembers(dealUserName(projectTask.getTaskMembers()));
        }
        projectTask.setHead(dealUserName(projectTask.getHead()));

        //任务交付物处理
        if(CollUtil.isNotEmpty(projectTask.getDeliverables())){
            projectTask.getDeliverables().forEach(deliverable -> {deliverable.setTaskCode(projectTask.getTaskCode());});
            JpaUtil.save(projectTask.getDeliverables());
        }
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            projectTask.setParentTaskName(parentTask.getTaskName());
            projectTask.setParentHead(parentTask.getHead());
        }

        //确定当前任务层级
        int level = 0;
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
            List<String> strings = new ArrayList<>();
            String parentTaskCode1 = projectTask.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode1,strings);
            level = rootTaskCodes.size();
            String strValue = Integer.toString(level);
            projectTask.setLevel(strValue+"级");

        }else {
            //如果当前任务没有父任务，则当前任务为根任务
            projectTask.setLevel("根任务");
        }

        this.update(projectTask);
        return Result.OK(projectTask);
    }

    private String dealUserName(String taskMembers){
        if(StrUtil.isEmpty(taskMembers)){
            return "";
        }
        taskMembers = StrUtil.addPrefixIfNot(taskMembers, ",");
        taskMembers = StrUtil.addSuffixIfNot(taskMembers, ",");

        return taskMembers;
    }

    /**
     * 获取当前父任务下的最大序号
     * @param parentTaskCode 父任务编码
     * @return 最大序号，如果没有子任务则返回0
     */
    private Integer getMaxNumberByParentTaskCode(String proCode, String parentTaskCode) {
        List<ProjectTask> siblingTasks = getSameLevelTasks(proCode, parentTaskCode);
        if (siblingTasks.isEmpty()) {
            return 0; // 如果没有子任务，则返回0
        } else {
            return siblingTasks.stream()
                    .map(ProjectTask::getNumber)
                    .filter(Objects::nonNull)
                    .max(Integer::compareTo)
                    .orElse(0); // 返回最大序号，如果找不到则返回0
        }
    }


    @Override
    @Transactional
    public void upgradeTask(String taskCode) {
        // 检查任务是否存在
        ProjectTask task = this.getById(ProjectTask.class, taskCode);
        if (task == null) {
           throw new MBootException("任务不存在");
        }
        if(!PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode().equals(task.getExecutionStatus())){
            throw new MBootException("当前任务状态不允许升级操作！");
        }
        if(StrUtil.isNotEmpty(task.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, task.getParentTaskCode());
            if(parentTask != null){
                task.setParentTaskCode(parentTask.getParentTaskCode());
                task.setParentTaskName(parentTask.getParentTaskName());
                task.setParentHead(parentTask.getParentHead());
                task.setNumber(getMaxNumberByParentTaskCode(task.getProCode(), task.getParentTaskCode()) + 1);
                this.update(task);
            }
        }
        //确定当前任务层级
        int level = 0;
        if (StrUtil.isNotEmpty(task.getParentTaskCode())){
            //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
            List<String> strings = new ArrayList<>();
            String parentTaskCode1 = task.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode1,strings);
            level = rootTaskCodes.size();
            String strValue = Integer.toString(level);
            task.setLevel(strValue+"级");

        }else {
            //如果当前任务没有父任务，则当前任务为根任务
            task.setLevel("根任务");
        }
        this.update(task);
    }

    @Override
    @Transactional
    public void downgradeTask(String taskCode) {
        // 获取当前任务信息
        ProjectTask currentTask = this.getById(ProjectTask.class, taskCode);
        if (currentTask == null) {
            return;
        }

        if(!PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode().equals(currentTask.getExecutionStatus())){
            throw new MBootException("当前任务状态不允许降级操作！");
        }

        // 获取同级任务
        List<ProjectTask> sameLevelTasks = getSameLevelTasks(currentTask.getProCode(), currentTask.getParentTaskCode());

        // 获取当前任务的同级别的第一个任务（不包括当前任务）
        ProjectTask firstSibling = sameLevelTasks.stream()
                .filter(task -> !task.getTaskCode().equals(taskCode)
                        && "10".equals(task.getTaskType())
                        && (task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode())
                                ||task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.EXECUTING.getCode())))
                .min(Comparator.comparing(ProjectTask::getNumber))
                .orElse(null);
        if (firstSibling == null) {
            throw new MBootException("没有同级别的其他任务或者当前任务已经是最低级别，无法进行降级操作！");
        }

        // 将当前任务作为新子任务添加到同级别的第一个任务下
        currentTask.setParentTaskCode(firstSibling.getTaskCode());
        currentTask.setParentTaskName(firstSibling.getTaskName());
        currentTask.setParentHead(firstSibling.getHead());
        currentTask.setNumber(getMaxNumberByParentTaskCode(currentTask.getProCode(), currentTask.getParentTaskCode()) + 1);

        // 更新当前任务
        this.update(currentTask);

        //确定当前任务层级
        int level = 0;
        if (StrUtil.isNotEmpty(currentTask.getParentTaskCode())){
            //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
            List<String> strings = new ArrayList<>();
            String parentTaskCode1 = currentTask.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode1,strings);
            level = rootTaskCodes.size();
            String strValue = Integer.toString(level);
            currentTask.setLevel(strValue+"级");

        }else {
            //如果当前任务没有父任务，则当前任务为根任务
            currentTask.setLevel("根任务");
        }
        this.update(currentTask);
    }




    @Override
    @Transactional
    public void moveTaskUp(String taskCode) {
        ProjectTask currentTask = this.getById(ProjectTask.class, taskCode);
        if(currentTask == null){
            return;
        }

        // 获取具有相同父任务编码且权重小于当前任务权重的最大权重任务
        List<ProjectTask> siblingTasks = this.getSameLevelTasks(currentTask.getProCode(), currentTask.getParentTaskCode());
        ProjectTask previousTask = siblingTasks.stream()
                .filter(task -> task.getNumber() < currentTask.getNumber())
                .max(Comparator.comparing(ProjectTask::getNumber))
                .orElse(null);

        if (previousTask != null) {
            // 交换权重
            Integer tempWeight = currentTask.getNumber();
            currentTask.setNumber(previousTask.getNumber());
            previousTask.setNumber(tempWeight);

            // 更新两个任务
            this.update(currentTask);
            this.update(previousTask);
        }
    }

    @Override
    @Transactional
    public void moveTaskDown(String taskCode) {
        ProjectTask currentTask = this.getById(ProjectTask.class, taskCode);
        if(currentTask == null){
            return;
        }

        // 获取具有相同父任务编码且权重大于当前任务权重的最小权重任务
        List<ProjectTask> siblingTasks = this.getSameLevelTasks(currentTask.getProCode(), currentTask.getParentTaskCode());
        ProjectTask nextTask = siblingTasks.stream()
                .filter(task -> task.getNumber() > currentTask.getNumber())
                .min(Comparator.comparing(ProjectTask::getNumber))
                .orElse(null);

        if (nextTask != null) {
            // 交换权重
            Integer tempWeight = currentTask.getNumber();
            currentTask.setNumber(nextTask.getNumber());
            nextTask.setNumber(tempWeight);

            // 更新两个任务
            this.update(currentTask);
            this.update(nextTask);
        }
    }

    @Override
    @Transactional
    public void start(ProjectTask projectTask) {
        //当有前置任务时
        String beforeTask = projectTask.getBeforeTask();
        if (beforeTask !=null && !beforeTask.equals("")){
            //完成-开始
            if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())){
                ProjectTask byId = this.getById(ProjectTask.class, beforeTask);//前置任务
                if (byId.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())){
                    String executionStatus = projectTask.getExecutionStatus();
                    projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.EXECUTING.getCode());
                    projectTask.setProgress(BigDecimal.ZERO); //任务进度初始化为0
                    this.update(projectTask);
                    //记录状态变更
                    projectTaskStatusHistoryService.record(projectTask, executionStatus);
                }else {
                    throw new MBootException("前置任务未完成，当前任务不允许开始");
                }
                //开始-开始
            }else if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.START_START.getCode())){
                ProjectTask byId = this.getById(ProjectTask.class, beforeTask);//前置任务
                if (!byId.getExecutionStatus().equals(PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode())){
                    String executionStatus = projectTask.getExecutionStatus();
                    projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.EXECUTING.getCode());
                    projectTask.setProgress(BigDecimal.ZERO); //任务进度初始化为0
                    this.update(projectTask);
                    //记录状态变更
                    projectTaskStatusHistoryService.record(projectTask, executionStatus);
                }else {
                    throw new MBootException("前置任务未开始，当前任务不允许开始");
                }
                //完成-完成 和 开始-完成不受影响
            }else if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())
                    ||projectTask.getTaskLink().equals(PlmEnums.TaskLink.START_END.getCode())){
                String executionStatus = projectTask.getExecutionStatus();
                projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.EXECUTING.getCode());
                projectTask.setProgress(BigDecimal.ZERO); //任务进度初始化为0
                this.update(projectTask);

                //记录状态变更
                projectTaskStatusHistoryService.record(projectTask, executionStatus);
            }

        }else {
            String executionStatus = projectTask.getExecutionStatus();
            projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.EXECUTING.getCode());
            projectTask.setProgress(BigDecimal.ZERO); //任务进度初始化为0
            this.update(projectTask);

            //判断-执行状态下-是否逾期
            LocalDate currentDate = LocalDate.now(); //获取当前时间
            Date planEndTime = projectTask.getPlanEndTime();//任务计划完工日期
            LocalDate planEndLocalDate = planEndTime.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();
            if (currentDate.isAfter(planEndLocalDate)) {
                long daysBetween = ChronoUnit.DAYS.between(planEndLocalDate, currentDate);
                if (daysBetween < 0) {
                    daysBetween = Math.abs(daysBetween);
                }
                String s = String.valueOf(daysBetween);
                projectTask.setOverdueDays(s);//当计划时间超过当前时间时，判断为当前项目延期
            }else {
                projectTask.setOverdueDays("0");//未逾期，逾期天数为0
            }
            this.update(projectTask);

            //记录状态变更
            projectTaskStatusHistoryService.record(projectTask, executionStatus);
        }
    }

    @Override
    @Transactional
    public void executeTask(ProjectTask projectTask, ProjectTaskBO projectTaskBO) {
        BigDecimal progress = projectTask.getProgress();
//        //判断前置任务是否已完成
//        if(StrUtil.isNotEmpty(projectTask.getBeforeTask())){
//            ProjectTask beforeTask = this.getById(ProjectTask.class, projectTask.getBeforeTask());
//            if(beforeTask == null || !PlmEnums.ExecutionStatus.FINISHED.getCode().equals(beforeTask.getExecutionStatus())){
//                throw new MBootException(String.format("前置任务[%s]未完成，请先完成前置任务！",beforeTask.getTaskName()));
//            }
//        }

        if(projectTask.getActualStartTime() == null){
            //任务执行日志的首次提报时间
            projectTask.setActualStartTime(new Date());
        }
        if(projectTaskBO.getProgress().compareTo(BigDecimal.valueOf(100)) == 0){
            //任务汇总执行进度为100%的执行日志提报时间
            projectTask.setActualEndTime(new Date());
        }
        projectTask.setProgress(projectTaskBO.getProgress());
//        projectTask.setNormalWorkTime(projectTaskBO.getNormalWorkTime());
//        projectTask.setOvertimeWorkTime(projectTaskBO.getOvertimeWorkTime());
        BigDecimal normalWorkTime = projectTask.getNormalWorkTime();//总正常工时
        BigDecimal overtimeWorkTime = projectTask.getOvertimeWorkTime();//总加班工时
        if (normalWorkTime == null) {
            projectTask.setNormalWorkTime(projectTaskBO.getOneNormalWorkTime());
        }else {
            if (projectTaskBO.getOneNormalWorkTime() != null){
                projectTask.setNormalWorkTime(normalWorkTime.add(projectTaskBO.getOneNormalWorkTime()));
            }
        }
        if (overtimeWorkTime == null){
            projectTask.setOvertimeWorkTime(projectTaskBO.getOneOvertimeWorkTime());
        }else {
            if (projectTaskBO.getOneOvertimeWorkTime()!=null){
                projectTask.setOvertimeWorkTime(overtimeWorkTime.add(projectTaskBO.getOneOvertimeWorkTime()));
            }
        }

        // 更新任务状态为"EXECUTING"
        projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.EXECUTING.getCode());
        this.update(projectTask);

        //更新交付物
        if (CollUtil.isNotEmpty(projectTaskBO.getDeliverables())) {
            JpaUtil.update(projectTaskBO.getDeliverables());
        }

        //记录状态变化
        ProjectTaskExecutionLog executionLog = new ProjectTaskExecutionLog();
        executionLog.setTaskCode(projectTask.getTaskCode());
        executionLog.setLogType(PlmEnums.LogType.EXECUTION.getCode());
        executionLog.setApplicant(projectTask.getUpdateBy());
        executionLog.setApplyTime(projectTask.getUpdateTime());
        executionLog.setOriProgress(progress);
        executionLog.setProgress(projectTaskBO.getProgress());
        executionLog.setNormalWorkTime(projectTaskBO.getOneNormalWorkTime());
        executionLog.setOvertimeWorkTime(projectTaskBO.getOneOvertimeWorkTime());
        executionLog.setProCode(projectTask.getProCode());
        JpaUtil.save(executionLog);

        List<ProjectTaskMembersTime> list = JpaUtil.linq(ProjectTaskMembersTime.class).equal("taskCode", projectTask.getTaskCode()).list();
        if (list == null) {
            ProjectTaskMembersTime taskMembersTime = new ProjectTaskMembersTime();
            taskMembersTime.setProCode(projectTask.getProCode());
            taskMembersTime.setTaskCode(projectTask.getTaskCode());
            taskMembersTime.setName(executionLog.getApplicant());
            if (projectTaskBO.getOneNormalWorkTime() != null){
                taskMembersTime.setNormalWorkTime(projectTaskBO.getOneNormalWorkTime());
            }else {
                taskMembersTime.setNormalWorkTime(BigDecimal.ZERO);
            }
            if (projectTaskBO.getOneOvertimeWorkTime() != null){
                taskMembersTime.setOvertimeWorkTime(projectTaskBO.getOneOvertimeWorkTime());
            }else {
                taskMembersTime.setOvertimeWorkTime(BigDecimal.ZERO);
            }

            projectTaskMembersTimeService.save(taskMembersTime);
        } else {
            for (ProjectTaskMembersTime projectTaskMembersTime : list) {
                if (projectTaskMembersTime.getName().equals(executionLog.getApplicant())) {//相等时，证明表中有相应的数据，相加即可
                    if (projectTaskBO.getOneNormalWorkTime()!=null){
                        projectTaskMembersTime.setNormalWorkTime(projectTaskMembersTime.getNormalWorkTime().add(projectTaskBO.getOneNormalWorkTime()));
                    }
                    if (projectTaskBO.getOneOvertimeWorkTime()!=null){
                        projectTaskMembersTime.setOvertimeWorkTime(projectTaskMembersTime.getOvertimeWorkTime().add(projectTaskBO.getOneOvertimeWorkTime()));
                    }
                    projectTaskMembersTimeService.update(projectTaskMembersTime);
                }
            }
            //找不到相等的人员说明没有，需要新增
            ProjectTaskMembersTime taskMembersTime = new ProjectTaskMembersTime();
            taskMembersTime.setProCode(projectTask.getProCode());
            taskMembersTime.setTaskCode(projectTask.getTaskCode());
            taskMembersTime.setName(executionLog.getApplicant());
            if (projectTaskBO.getOneNormalWorkTime() != null){
                taskMembersTime.setNormalWorkTime(projectTaskBO.getOneNormalWorkTime());
            }else {
                taskMembersTime.setNormalWorkTime(BigDecimal.ZERO);
            }
            if (projectTaskBO.getOneOvertimeWorkTime() != null){
                taskMembersTime.setOvertimeWorkTime(projectTaskBO.getOneOvertimeWorkTime());
            }else {
                taskMembersTime.setOvertimeWorkTime(BigDecimal.ZERO);
            }
            projectTaskMembersTimeService.save(taskMembersTime);
        }
    }



    private boolean checkApplyTask(ProjectTask projectTask) {
        List<ProjectTaskExecutionLog> list = JpaUtil.linq(ProjectTaskExecutionLog.class)
                .in("logType", PlmEnums.LogType.COMPLETE.getCode(), PlmEnums.LogType.CHANGE.getCode(), PlmEnums.LogType.CLOSE.getCode(),PlmEnums.LogType.COMPLETEWORKFLOW.getCode())
                .equal("taskCode", projectTask.getTaskCode())
                .equal("auditStatus", OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())
                .list();

        return list.isEmpty();
    }

    @Override
    @Transactional
    public void finishTask(ProjectTask projectTask, ProjectTaskBO projectTaskBO) {
        //判断前置任务
        String beforeTask = projectTask.getBeforeTask();
        if (beforeTask !=null && !beforeTask.equals("")){
            //开始-完成
            if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.START_END.getCode())){
                ProjectTask byId = this.getById(ProjectTask.class, beforeTask);
                if (byId.getExecutionStatus().equals(PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode())){
                    throw new MBootException("前置任务未开始，当前任务不允许完工");
                }
            }
            //完成-完成
            if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                ProjectTask byId = this.getById(ProjectTask.class, beforeTask);
                if (!byId.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())){
                    throw new MBootException("前置任务未完工，当前任务不允许完工");
                }
            }
        }
        //校验子任务是否已完成
        List<ProjectTask> childTasks = JpaUtil.linq(ProjectTask.class)
                .equal("parentTaskCode", projectTask.getTaskCode())
                .in("executionStatus", PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode(), PlmEnums.ExecutionStatus.EXECUTING.getCode())
                .list();
        if(!childTasks.isEmpty()){
            String taskCodes = childTasks.stream().map(ProjectTask::getTaskCode).collect(Collectors.joining(","));
            throw new MBootException(String.format("子任务[%s]未完成，请先处理子任务！",taskCodes));
        }

        //校验当前任务是否存在审核中的完工申请
        if(!checkApplyTask(projectTask)){
            String taskHead = getThePersonInChargeOfTheAudit(projectTask);
            throw new MBootException("当前任务存在未完成的申请，请先审核！"+"\n"+
                    "任务编码："+projectTask.getTaskCode()+"\n"+
                    "任务名称："+projectTask.getTaskName()+"\n"+
                    "任务审核人："+taskHead);
        }

        //记录log
        ProjectTaskExecutionLog executionLog = new ProjectTaskExecutionLog();
        BeanUtil.copyProperties(projectTask, executionLog, "crudType", "saveTransient","deliverables");

        executionLog.setTaskCode(projectTask.getTaskCode());
        executionLog.setLogType(PlmEnums.LogType.COMPLETE.getCode());
        executionLog.setApplicant(SecurityUtils.getLoginUsername());
        executionLog.setApplyTime(new Date());
        executionLog.setOriProgress(projectTask.getProgress());
        executionLog.setApplyDesc(projectTaskBO.getApplyDesc() !=null ? projectTaskBO.getApplyDesc():null);//说明
        executionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        executionLog.setHead(getTaskHead(projectTask));
        executionLog.setHeadTask(projectTask.getHead());
        executionLog.setProCode(projectTask.getProCode());
        executionLog.setActualStartTime(projectTaskBO.getActualStartTime());//实际开始日期
        executionLog.setActualEndTime(projectTaskBO.getActualEndTime());//实际结束日期
        executionLog.setActualDuration(projectTaskBO.getActualDuration()!=null ?projectTaskBO.getActualDuration():null);//实际工期（天）
        executionLog.setNormalWorkTime(projectTaskBO.getOneNormalWorkTime() !=null ? projectTaskBO.getOneNormalWorkTime():null);//正常工时
        executionLog.setOvertimeWorkTime(projectTaskBO.getOneOvertimeWorkTime()!=null ? projectTaskBO.getOneOvertimeWorkTime():null);//加班工时
        executionLog.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());

//        executionLog.setNormalWorkTime(projectTask.getNormalWorkTime());
//        executionLog.setOvertimeWorkTime(projectTask.getOvertimeWorkTime());
        JpaUtil.save(executionLog);
        //存入项目任务-审核记录
        ProjectTaskAuditRecords records = new ProjectTaskAuditRecords();
        records.setTaskLogId(executionLog.getId());
        records.setTaskCode(projectTask.getTaskCode());
        records.setProCode(projectTask.getProCode());
        records.setOperationalNodes("30");//完工
        records.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        records.setApplyTime(new Date());
        records.setApplicant(SecurityUtils.getLoginUsername());
        records.setReason(projectTaskBO.getApplyDesc());
        projectTaskAuditRecordsService.save(records);


        //存入交付物草稿表
        List<ProjectTaskDeliverable> deliverables = projectTaskBO.getDeliverables();
        for (ProjectTaskDeliverable deliverable : deliverables){
            ProjectTaskCompleteDeliverableDraft draft = new ProjectTaskCompleteDeliverableDraft();
            BeanUtil.copyProperties(deliverable, draft,"crudType","saveTransient","id");
            draft.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());
            draft.setTaskLogId(executionLog.getId());
            projectTaskCompleteDeliverableDraftService.save(draft);
        }
        String[] toUsers = {getThePersonInChargeOfTheAudit(projectTask)};
        //发送站内信
        messageService.sendMessage(channelCodes,SecurityUtils.getLoginUsername(),toUsers,"项目任务审核提醒","任务完工");

    }



    public String getThePersonInChargeOfTheAudit(ProjectTask projectTask) {
        if (projectTask.getParentTaskCode() == null){ //根任务
            ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, projectTask.getProCode());
            return projectInfo.getProLeader();
        }else {
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            return parentTask.getHead();
        }
    }


    @Override
    @Transactional
    public void finishAudit(ProjectTask projectTask, ProjectTaskBO projectTaskBO) {
        ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());
        if(taskExecutionLog == null || !OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode().equals(taskExecutionLog.getAuditStatus())){
            throw new MBootException("完工申请状态错误！");
        }
        //更新任务状态 ,同意
        if(CommonEnums.YesNo.YES.getCode().equals(projectTaskBO.getAuditOpinion())){
            String executionStatus = projectTask.getExecutionStatus();
            projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.FINISHED.getCode());
            projectTask.setProgress(new BigDecimal("100"));
            this.update(projectTask);

            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);
            //计算项目进度
            List<ProjectTask> tasks = this.list(ProjectTask.class, Criteria.create().addCriterion("proCode", Operator.EQ,projectTask.getProCode()));
            int size = 0;
            int finished = 0;
            for (ProjectTask task : tasks){
                if (task.getTaskType().equals("10") && !task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.CLOSED.getCode())){//只计算项目任务的进度
                    size += 1;

                    if (task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())){
                        finished += 1;
                    }
                }
            }
            ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, projectTask.getProCode());
            BigDecimal progress = new BigDecimal(finished).divide(new BigDecimal(size),2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
            projectInfo.setSchedule(progress);
            projectInfoService.update(projectInfo);
            //记录审核意见
            taskExecutionLog.setAuditOpinion(projectTaskBO.getAuditOpinion());
            taskExecutionLog.setAuditOpinionDesc(projectTaskBO.getAuditOpinionDesc());
            taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
            taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
            taskExecutionLog.setAuditTime(new Date());
            taskExecutionLog.setProCode(projectTask.getProCode());
            taskExecutionLog.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
            projectTaskExecutionLogService.update(taskExecutionLog);

            //存入项目任务-审核记录
            ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", taskExecutionLog.getId()).findOne();
            one.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
            one.setAuditTime(new Date());
            projectTaskAuditRecordsService.update(one);



//            //回写交付物
//            List<ProjectTaskCompleteDeliverableDraft> deliverableDrafts= projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode",Operator.EQ, projectTaskBO.getTaskCode()));
//            for (ProjectTaskCompleteDeliverableDraft deliverableDraft : deliverableDrafts){
//                if (deliverableDraft.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())){
//                    ProjectTaskDeliverable deliverable = JpaUtil.linq(ProjectTaskDeliverable.class).equal("docNO", deliverableDraft.getDocNO()).findOne();
//                    deliverable.setDocFile(deliverableDraft.getDocFile());
//                    projectTaskDeliverableService.update(deliverable);
//                }
//            }


        }else {//当不同意的时候 ， 更改任务交付草稿表的信息
            String executionStatus = projectTask.getExecutionStatus();
            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);

            //任务交付物审核结束
            List<ProjectTaskCompleteDeliverableDraft> list = projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTask.getTaskCode()));
            for (ProjectTaskCompleteDeliverableDraft projectTaskCompleteDeliverableDraft : list){
                projectTaskCompleteDeliverableDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
                projectTaskCompleteDeliverableDraftService.update(projectTaskCompleteDeliverableDraft);
            }

                //记录审核意见
                taskExecutionLog.setAuditOpinion(projectTaskBO.getAuditOpinion());
                taskExecutionLog.setAuditOpinionDesc(projectTaskBO.getAuditOpinionDesc());
                taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
                taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
                taskExecutionLog.setAuditTime(new Date());
                taskExecutionLog.setProCode(projectTask.getProCode());
                taskExecutionLog.setBpmnStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
                projectTaskExecutionLogService.update(taskExecutionLog);

            //存入项目任务-审核记录
            ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", taskExecutionLog.getId()).findOne();
            one.setBpmnStatus("不同意");
            one.setAuditTime(new Date());
            projectTaskAuditRecordsService.update(one);


        }
    }

    @Override
    @Transactional
    public void changeTask(ProjectTask projectTask) {
        //校验当前任务是否存在审核中的变更申请
        if(!checkApplyTask(projectTask)){
            String taskHead = getThePersonInChargeOfTheAudit(projectTask);
            throw new MBootException("当前任务存在未完成的申请，请先审核！"+"\n"+
                    "任务编码："+projectTask.getTaskCode()+"\n"+
                    "任务名称："+projectTask.getTaskName()+"\n"+
                    "任务审核人："+taskHead);
        }

        //任务计划开始和计划结束时间不要再项目计划和结束之间
        //获取任务模板的计划开始时间和计划结束时间
        Date planStartTime = projectTask.getPlanStartTime();
        Date planEndTime = projectTask.getPlanEndTime();
        String proCode = projectTask.getProCode();
        ProjectInfo one1 = JpaUtil.linq(ProjectInfo.class).equal("proCode", proCode).findOne();
        //获取项目计划开始时间和项目计划结束时间
        Date proPlanStartTime = one1.getPlanStartTime();
        Date proPlanEndTime = one1.getPlanEndTime();
        //判断任务计划开始时间和计划结束时间是否在项目计划和结束之间
        if (planStartTime.before(proPlanStartTime) || planStartTime.after(proPlanEndTime) || planEndTime.before(proPlanStartTime) || planEndTime.after(proPlanEndTime)){
            throw new MBootException("任务计划开始时间和计划结束时间必须在项目计划和结束时间之间" +"\n"+
                    "项目计划开始时间："+proPlanStartTime+"\n" +
                    "项目计划结束时间："+proPlanEndTime);
        }
        //为子级任务时，计划开始和结束需在父级时间内
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            //判断子级任务计划开始和结束时间是否在父级任务计划时间内
            if(parentTask.getPlanStartTime().after(planStartTime) || parentTask.getPlanEndTime().before(planEndTime)){
                throw new MBootException("子级任务计划开始和结束时间必须在父级任务计划时间内");
            }
        }
        //当前任务的前置任务与父级任务相等时，关联关系不能选择完成-开始，完成-完成
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            if (StrUtil.equals(projectTask.getBeforeTask(), projectTask.getParentTaskCode())){
                if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())||
                        projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                    throw new MBootException("前置任务与父级任务相等时，关联关系不能选择完成-开始，完成-完成");
                }
            }
        }

        //当前任务的前置任务与根任务相等时，关联关系不能选择完成-开始，完成-完成
        if (StrUtil.isNotEmpty(projectTask.getParentTaskCode())&& StrUtil.isNotEmpty(projectTask.getBeforeTask())) {
            List<String> strings = new ArrayList<>();
            String parentTaskCode = projectTask.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode,strings);
            for (String rootTaskCode : rootTaskCodes){
                if (projectTask.getBeforeTask().equals(rootTaskCode)){
                    if (projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_START.getCode())||
                            projectTask.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                        throw new MBootException("前置任务为父级任务时，关联关系不能选择完成-开始，完成-完成");
                    }
                }
            }
        }


        //校验父任务状态
        if(StrUtil.isNotEmpty(projectTask.getParentTaskCode())){
            ProjectTask parentTask = this.getById(ProjectTask.class, projectTask.getParentTaskCode());
            if(parentTask.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())){
                throw new MBootException("父任务已完成，不能添加子任务");
            }
        }

        //记录log
        ProjectTaskExecutionLog executionLog = new ProjectTaskExecutionLog();
        BeanUtil.copyProperties(projectTask, executionLog, "crudType", "saveTransient","deliverables");

        executionLog.setTaskCode(projectTask.getTaskCode());
        executionLog.setLogType(PlmEnums.LogType.CHANGE.getCode());
        executionLog.setApplicant(SecurityUtils.getLoginUsername());
        executionLog.setApplyTime(new Date());
        executionLog.setOriProgress(projectTask.getProgress());
        executionLog.setApplyDesc(projectTask.getApplyDesc());
        executionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        executionLog.setHead(getTaskHead(projectTask));
        executionLog.setHeadTask(projectTask.getHead());
        executionLog.setNormalWorkTime(projectTask.getNormalWorkTime());
        executionLog.setOvertimeWorkTime(projectTask.getOvertimeWorkTime());
        executionLog.setProCode(projectTask.getProCode());
        executionLog.setWorkflowId(projectTask.getWorkflowId());//工作流ID
        executionLog.setApprovalPlan(projectTask.getApprovalPlan());
        JpaUtil.save(executionLog);

        //处理任务成员、负责人
        if (projectTask.getTaskMembers()!=null){
            projectTask.setTaskMembers(dealUserName(projectTask.getTaskMembers()));
        }
        projectTask.setHead(dealUserName(projectTask.getHead()));

        //存入项目任务-审核记录
        ProjectTaskAuditRecords records = new ProjectTaskAuditRecords();
        records.setTaskLogId(executionLog.getId());
        records.setTaskCode(projectTask.getTaskCode());
        records.setProCode(projectTask.getProCode());
        records.setOperationalNodes("10");//变更
        records.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        records.setApplyTime(new Date());
        records.setApplicant(SecurityUtils.getLoginUsername());
        records.setReason(executionLog.getApplyDesc());
        projectTaskAuditRecordsService.save(records);

        //将变更申请的任务暂存
        ProjectTaskDraft projectTaskDraft = new ProjectTaskDraft();
        BeanUtil.copyProperties(projectTask, projectTaskDraft,"createBy","createDept","createTime","crudType","saveTransient");
        projectTaskDraft.setTaskLogId(executionLog.getId());
        projectTaskDraft.setApplyDesc(projectTask.getApplyDesc());
        projectTaskDraft.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());
        JpaUtil.save(projectTaskDraft);

        //任务交付物处理
//        if(CollUtil.isNotEmpty(projectTask.getDeliverables())){
//            projectTask.getDeliverables().forEach(deliverable -> {
//                deliverable.setId(null);
//                deliverable.setTaskCode(projectTaskDraft.getId());
//                deliverable.setCrudType(CrudType.SAVE);
//            });
//            JpaUtil.save(projectTask.getDeliverables());
//        }
        //修改的交付物
        List<ProjectTaskDeliverable> deliverables = projectTask.getDeliverables();
        //原始的交付物
        Criteria criteria = Criteria.create().addCriterion("taskCode", Operator.EQ, projectTask.getTaskCode());
        List<ProjectTaskDeliverable> list = projectTaskDeliverableService.list(ProjectTaskDeliverable.class, criteria);//取出本身的交付物
        if (deliverables.size() > 0 && list.size() > 0) {
            List<String> updateDeliverables = deliverables.stream()
                    .map(ProjectTaskDeliverable::getDocNO)
                    .collect(Collectors.toList());

            List<String> taskDeliverable = list.stream()
                    .map(ProjectTaskDeliverable::getDocNO) // 假设ProjectDeliverable类有一个getDocNO方法返回docNO属性
                    .collect(Collectors.toList());
            //得出没有被修改的交付物
            List<String> differentDeliverables = taskDeliverable.stream()
                    .filter(docNO -> !updateDeliverables.contains(docNO))
                    .collect(Collectors.toList());
            for (String docNO : differentDeliverables) {
                ProjectTaskDeliverable one = JpaUtil.linq(ProjectTaskDeliverable.class).equal("docNO", docNO).findOne();
                ProjectTaskDeliverableDraft draft = new ProjectTaskDeliverableDraft();
                //此交付物没有修改，存入草稿表
                BeanUtil.copyProperties(one, draft, "id", "taskCode", "crudType");
                draft.setTaskLogId(executionLog.getId());
                draft.setTaskCode(projectTask.getTaskCode());
                projectTaskDeliverableDraftService.save(draft);

            }
        }
        if (deliverables != null && deliverables.size() > 0) {//当有修改的数据时
            for (ProjectTaskDeliverable deliverable : deliverables) {
                ProjectTaskDeliverableDraft draft = new ProjectTaskDeliverableDraft();
                if (!deliverable.getCrudType().name().equals("DELETE")) {
                    BeanUtil.copyProperties(deliverable, draft, "id", "taskCode", "crudType");
                    draft.setTaskCode(projectTask.getTaskCode());
                    draft.setTaskLogId(executionLog.getId());
                    projectTaskDeliverableDraftService.save(draft);
                }
            }
        }else for (ProjectTaskDeliverable deliverable1 : list) {
            ProjectTaskDeliverableDraft draft = new ProjectTaskDeliverableDraft();
            //此交付物没有修改，存入草稿表
            BeanUtil.copyProperties(deliverable1, draft, "id", "proCode", "crudType");
            draft.setTaskCode(projectTask.getTaskCode());
            draft.setTaskLogId(executionLog.getId());
            projectTaskDeliverableDraftService.save(draft);
        }
        String[] toUsers = {getThePersonInChargeOfTheAudit(projectTask)};
        //发送站内信
        messageService.sendMessage(channelCodes,SecurityUtils.getLoginUsername(),toUsers,"项目任务审核提醒","任务变更");

    }

    @Override
    @Transactional
    public void changeAudit(ProjectTask projectTask, ProjectTaskBO projectTaskBO) {
        ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());
        if(taskExecutionLog == null || !OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode().equals(taskExecutionLog.getAuditStatus())){
            throw new MBootException("变更申请状态错误！");
        }

        List<ProjectTaskDraft> taskDrafts = JpaUtil.linq(ProjectTaskDraft.class).equal("taskLogId", taskExecutionLog.getId()).list();
        if(taskDrafts == null || taskDrafts.isEmpty()){
            throw new MBootException("变更申请任务不存在！");
        }
        ProjectTaskDraft projectTaskDraft = taskDrafts.get(0);
        if (projectTaskDraft.getIsAuditEnd() ==null ||projectTaskDraft.getIsAuditEnd() .equals(CommonEnums.YesNo.NO.getCode())){
            //更新任务字段
            if(CommonEnums.YesNo.YES.getCode().equals(projectTaskBO.getAuditOpinion())){
                projectTaskDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
                JpaUtil.update(projectTaskDraft);
                //更新任务
                BeanUtil.copyProperties(projectTaskDraft, projectTask,"createBy","createDept","createTime","crudType","saveTransient");
                this.update(projectTask);
                //任务交付物
                //删除变更前的任务交付物
                JpaUtil.lind(ProjectTaskDeliverable.class).equal("taskCode", projectTaskDraft.getTaskCode()).delete();
                //查询变更后的任务交付物
//            List<ProjectTaskDeliverable> deliverables = JpaUtil.linq(ProjectTaskDeliverable.class).equal("taskCode", projectTaskDraft.getId()).list();
                //任务交付物处理
//            if(CollUtil.isNotEmpty(deliverables)){
//                deliverables.forEach(deliverable -> {
//                    deliverable.setId(null);
//                    deliverable.setTaskCode(projectTaskDraft.getTaskCode());
//                    deliverable.setCrudType(CrudType.SAVE);
//                });
//                JpaUtil.save(deliverables);
//            }
                Criteria criteria = Criteria.create().addCriterion("taskCode", Operator.EQ, projectTask.getTaskCode());
                List<ProjectTaskDeliverableDraft> list = projectTaskDeliverableDraftService.list(ProjectTaskDeliverableDraft.class, criteria);//查找草稿表交付
                for (ProjectTaskDeliverableDraft draft1 : list){
                    if (draft1.getIsAuditEnd() ==null ||draft1.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())){
                        draft1.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
                        projectTaskDeliverableDraftService.update(draft1);
                        ProjectTaskDeliverable deliverable = new ProjectTaskDeliverable();
                        BeanUtil.copyProperties(draft1,deliverable,"id");
                        projectTaskDeliverableService.save(deliverable);
                    }
                }

                //存入项目任务-审核记录
                ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", projectTaskBO.getTaskLogId()).findOne();
                one.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
                one.setAuditTime(new Date());
                projectTaskAuditRecordsService.update(one);

                //记录审核意见
                taskExecutionLog.setAuditOpinion(projectTaskBO.getAuditOpinion());
                taskExecutionLog.setAuditOpinionDesc(projectTaskBO.getAuditOpinionDesc());
                taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
                taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
                taskExecutionLog.setAuditTime(new Date());
                projectTaskExecutionLogService.update(taskExecutionLog);

//                projectTaskDeliverableDraftService.deleteBatch(ProjectTaskDeliverableDraft.class, criteria);//删除草稿表的交付物

            }else {//变更 不同意
                projectTaskDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
                JpaUtil.update(projectTaskDraft);
                Criteria criteria = Criteria.create().addCriterion("taskCode", Operator.EQ, projectTask.getTaskCode());
                List<ProjectTaskDeliverableDraft> list = projectTaskDeliverableDraftService.list(ProjectTaskDeliverableDraft.class, criteria);//查找草稿表交付
                for (ProjectTaskDeliverableDraft draft1 : list){
                    draft1.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
                    projectTaskDeliverableDraftService.update(draft1);
                }
                //记录审核意见
                taskExecutionLog.setAuditOpinion(projectTaskBO.getAuditOpinion());
                taskExecutionLog.setAuditOpinionDesc(projectTaskBO.getAuditOpinionDesc());
                taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
                taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
                taskExecutionLog.setAuditTime(new Date());
                projectTaskExecutionLogService.update(taskExecutionLog);
                //存入项目任务-审核记录
                ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", projectTaskBO.getTaskLogId()).findOne();
                one.setBpmnStatus("不同意");
                one.setAuditTime(new Date());
                projectTaskAuditRecordsService.update(one);
            }

        }

    }

    @Override
    @Transactional
    public void deleteTask(String taskCode) {
        ProjectTask task = this.getById(ProjectTask.class, taskCode);
        if(task == null){
            return;
        }
        List<ProjectTask> childrenTasks = this.getChildrenTasks(task.getProCode(), taskCode);
        List<String> taskCodes = childrenTasks.stream().map(ProjectTask::getTaskCode).collect(Collectors.toList());
        taskCodes.add(taskCode);
        JpaUtil.lind(ProjectTask.class).in("taskCode", taskCodes).delete();
    }

    @Override
    @Transactional
    public void closeTask(ProjectTask projectTask, ProjectTaskBO projectTaskBO) {
        //校验当前任务是否存在审核中的关闭申请
        if(!checkApplyTask(projectTask)){
                String taskHead = getThePersonInChargeOfTheAudit(projectTask);
                throw new MBootException("当前任务存在未完成的申请，请先审核！"+"\n"+
                        "任务编码："+projectTask.getTaskCode()+"\n"+
                        "任务名称："+projectTask.getTaskName()+"\n"+
                        "任务审核人："+taskHead);
        }

        //记录log
        ProjectTaskExecutionLog executionLog = new ProjectTaskExecutionLog();
        BeanUtil.copyProperties(projectTask, executionLog, "crudType", "saveTransient","deliverables");

        executionLog.setTaskCode(projectTask.getTaskCode());
        executionLog.setLogType(PlmEnums.LogType.CLOSE.getCode());
        executionLog.setApplicant(SecurityUtils.getLoginUsername());
        executionLog.setApplyTime(new Date());
        executionLog.setOriProgress(projectTask.getProgress());
        executionLog.setApplyDesc(projectTaskBO.getApplyDesc());
        executionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        executionLog.setHead(getTaskHead(projectTask));
        executionLog.setHeadTask(projectTask.getHead());
        executionLog.setNormalWorkTime(projectTask.getNormalWorkTime());
        executionLog.setOvertimeWorkTime(projectTask.getOvertimeWorkTime());
        executionLog.setProCode(projectTask.getProCode());
        JpaUtil.save(executionLog);

        projectTask.setApplyDesc(projectTaskBO.getApplyDesc());
        this.update(projectTask);

        //存入项目任务-审核记录
        ProjectTaskAuditRecords records = new ProjectTaskAuditRecords();
        records.setTaskLogId(executionLog.getId());
        records.setTaskCode(projectTask.getTaskCode());
        records.setProCode(projectTask.getProCode());
        records.setOperationalNodes("20");//关闭
        records.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        records.setApplyTime(new Date());
        records.setApplicant(SecurityUtils.getLoginUsername());
        records.setReason(executionLog.getApplyDesc());
        projectTaskAuditRecordsService.save(records);

        //存入交付物
        List<ProjectTaskDeliverable> deliverables = projectTaskDeliverableService.list(ProjectTaskDeliverable.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTask.getTaskCode()));
        for (ProjectTaskDeliverable projectTaskDeliverable : deliverables){
            ProjectTaskEndDeliverableDraft projectTaskEndDeliverableDraft = new ProjectTaskEndDeliverableDraft();
            BeanUtil.copyProperties(projectTaskDeliverable, projectTaskEndDeliverableDraft,"id");
            projectTaskEndDeliverableDraft.setTaskLogId(executionLog.getId());
            projectTaskEndDeliverableDraftService.save(projectTaskEndDeliverableDraft);
        }


        String[] toUsers = {getThePersonInChargeOfTheAudit(projectTask)};
        //发送站内信
        messageService.sendMessage(channelCodes,SecurityUtils.getLoginUsername(),toUsers,"项目任务审核提醒","任务关闭");
    }

    @Override
    @Transactional
    public void closeTaskAudit(ProjectTask projectTask, ProjectTaskBO projectTaskBO) {
        ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());
        if (taskExecutionLog == null || !OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode().equals(taskExecutionLog.getAuditStatus())) {
            throw new MBootException("关闭申请状态错误！");
        }
        //更新任务状态
        if (CommonEnums.YesNo.YES.getCode().equals(projectTaskBO.getAuditOpinion())) {
            String executionStatus = projectTask.getExecutionStatus();
            projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.CLOSED.getCode());
            this.update(projectTask);
            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);


        //当此任务为，当前项目的最后一个任务进行关闭时，这时项目进度要为100
        Criteria criteria = Criteria.create().addCriterion("proCode", Operator.EQ, projectTask.getProCode());
        List<ProjectTask> tasks = this.list(ProjectTask.class, criteria);
        int count = 0;
        for (ProjectTask task : tasks) {
            if (task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.CLOSED.getCode())
                    || task.getExecutionStatus().equals(ProjectTaskEnums.ExecutionStatus.FINISHED.getCode())) {
                count += 1;
            }
        }
        if (count == tasks.size()) {
            ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, projectTask.getProCode());
            BigDecimal hundred = new BigDecimal("100");
            projectInfo.setSchedule(hundred);
            projectInfoService.update(projectInfo);
        }
        //存入项目任务-审核记录
        ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", projectTaskBO.getTaskLogId()).findOne();
        one.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
        one.setAuditTime(new Date());
        projectTaskAuditRecordsService.update(one);


        //记录审核意见
        taskExecutionLog.setAuditOpinion(projectTaskBO.getAuditOpinion());
        taskExecutionLog.setAuditOpinionDesc(projectTaskBO.getAuditOpinionDesc());
        taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
        taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
        taskExecutionLog.setAuditTime(new Date());
        projectTaskExecutionLogService.update(taskExecutionLog);
        }else {
            //存入项目任务-审核记录
            ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", projectTaskBO.getTaskLogId()).findOne();
            one.setBpmnStatus("不同意");
            one.setAuditTime(new Date());
            projectTaskAuditRecordsService.update(one);


            //记录审核意见
            taskExecutionLog.setAuditOpinion(projectTaskBO.getAuditOpinion());
            taskExecutionLog.setAuditOpinionDesc(projectTaskBO.getAuditOpinionDesc());
            taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
            taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
            taskExecutionLog.setAuditTime(new Date());
            projectTaskExecutionLogService.update(taskExecutionLog);

        }
    }

    @Override
    @Transactional
    public void change(ProjectInfo projectInfo) {
        List<ProjectTask> tasks = this.list(ProjectTask.class, Criteria.create().addCriterion("proCode", Operator.EQ, projectInfo.getProCode()));
        if (tasks != null && tasks.size() > 0) {
            for (ProjectTask task : tasks){
                task.setProName(projectInfo.getProName());
                task.setProStatus(projectInfo.getProStatus());
                task.setProLeader(projectInfo.getProLeader());
                this.update(task);
            }
        }

    }

    @Override
    @Transactional
    public Result<?> finishAuditWorkflows(ProjectTaskBO projectTaskBO) {
        ProjectTask byId = this.getById(ProjectTask.class, projectTaskBO.getTaskCode());

        //校验子任务是否已完成
        List<ProjectTask> childTasks = JpaUtil.linq(ProjectTask.class)
                .equal("parentTaskCode", projectTaskBO.getTaskCode())
                .in("executionStatus", PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode(), PlmEnums.ExecutionStatus.EXECUTING.getCode())
                .list();
        if (!childTasks.isEmpty()) {
            String taskCodes = childTasks.stream().map(ProjectTask::getTaskCode).collect(Collectors.joining(","));
            return Result.error(String.format("子任务[%s]未完成，请先处理子任务！", taskCodes));
        }

        if (projectTaskBO.getBpmnStatus() != null) {
            if (!projectTaskBO.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode()) &&
                    !projectTaskBO.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode())) {
                List<ProjectTaskComplete> completes = projectTaskCompleteService.list(ProjectTaskComplete.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTaskBO.getTaskCode()));
                {
                    for (ProjectTaskComplete taskComplete : completes) {
                        if (taskComplete.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())) {
                            return Result.error("有未完成的审核，请勿重复提交！");
                        }
                    }
                }
            }
        }
        if (projectTaskBO.getBpmnStatus() == null) {
            //记录log
            ProjectTask projectTask = this.getById(ProjectTask.class, projectTaskBO.getTaskCode());
            ProjectTaskExecutionLog executionLog = new ProjectTaskExecutionLog();
            BeanUtil.copyProperties(byId, executionLog, "crudType", "saveTransient","deliverables");

            executionLog.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());//判断是否是工作流的
            executionLog.setTaskCode(projectTask.getTaskCode());
            executionLog.setLogType(PlmEnums.LogType.COMPLETE.getCode());
            executionLog.setApplicant(SecurityUtils.getLoginUsername());
            executionLog.setApplyTime(new Date());
            executionLog.setOriProgress(projectTask.getProgress());
            executionLog.setApplyDesc(projectTaskBO.getApplyDesc() !=null ? projectTaskBO.getApplyDesc():null);//说明
            executionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
            executionLog.setHead(getTaskHead(projectTask));
            executionLog.setHeadTask(projectTask.getHead());
            executionLog.setProCode(projectTask.getProCode());
            executionLog.setActualStartTime(projectTaskBO.getActualStartTime());//实际开始日期
            executionLog.setActualEndTime(projectTaskBO.getActualEndTime());//实际结束日期
            executionLog.setActualDuration(projectTaskBO.getActualDuration()!=null ?projectTaskBO.getActualDuration():null);//实际工期（天）
            executionLog.setNormalWorkTime(projectTaskBO.getOneNormalWorkTime() !=null ? projectTaskBO.getOneNormalWorkTime():null);//正常工时
            executionLog.setOvertimeWorkTime(projectTaskBO.getOneOvertimeWorkTime()!=null ? projectTaskBO.getOneOvertimeWorkTime():null);//加班工时
//            executionLog.setNormalWorkTime(projectTaskComplete.getNormalWorkTime());
//            executionLog.setOvertimeWorkTime(projectTaskComplete.getOvertimeWorkTime());
            JpaUtil.save(executionLog);

//            ProjectTaskComplete taskComplete = new ProjectTaskComplete();
//            BeanUtil.copyProperties(byId, taskComplete, "crudType", "saveTransient","deliverables");
//            BeanUtil.copyProperties(projectTaskComplete, taskComplete, "crudType", "saveTransient","deliverables");
//            taskComplete.setApplicant(SecurityUtils.getLoginUsername());
//            taskComplete.setApplyTime(new Date());
//            taskComplete.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
////            taskComplete.setId(executionLog.getId());
//            taskComplete.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());//是否审核结束 1是 0否
//            taskComplete.setWorkflowId(projectTaskComplete.getWorkflowId());
//            projectTaskCompleteService.save(taskComplete);

//            projectTask.setWorkflowId(projectTaskComplete.getWorkflowId());//存入申请单的ID
//            this.update(projectTask);
            //存交付物进任务交付物模板
            if (projectTaskBO.getDeliverables() != null) {
                List<ProjectTaskDeliverable> deliverables = projectTaskBO.getDeliverables();
                for (ProjectTaskDeliverable deliverable : deliverables) {
                    ProjectTaskCompleteDeliverableDraft draft = new ProjectTaskCompleteDeliverableDraft();
                    BeanUtil.copyProperties(deliverable, draft, "crudType", "saveTransient", "id");
                    draft.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());
                    projectTaskCompleteDeliverableDraftService.save(draft);
                }
            }
            return Result.OK(executionLog);
        }

        //当审核通过时
        if (projectTaskBO.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
            ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());

            ProjectTask projectTask = this.getById(ProjectTask.class, projectTaskBO.getTaskCode());
//            //更改该申请单
//            ProjectTaskComplete taskComplete = JpaUtil.linq(ProjectTaskComplete.class).equal("taskCode", projectTaskBO.getTaskCode()).findOne();
//            taskComplete.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
//            projectTaskCompleteService.update(taskComplete);

            String executionStatus = projectTask.getExecutionStatus();
            projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.FINISHED.getCode());
            projectTask.setNormalWorkTime(taskExecutionLog.getNormalWorkTime() !=null ? taskExecutionLog.getNormalWorkTime():null);
            projectTask.setOvertimeWorkTime(taskExecutionLog.getOvertimeWorkTime()!=null ? taskExecutionLog.getOvertimeWorkTime():null);
            projectTask.setActualDuration(taskExecutionLog.getActualDuration()!=null ?taskExecutionLog.getActualDuration():null);
            projectTask.setActualEndTime(taskExecutionLog.getActualEndTime());
            projectTask.setActualStartTime(taskExecutionLog.getActualStartTime());
            projectTask.setProgress(new BigDecimal("100"));
            this.update(projectTask);
//            //回写交付物
//            List<ProjectTaskCompleteDeliverableDraft> deliverableDrafts= projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode",Operator.EQ, projectTaskComplete.getTaskCode()));
//            for (ProjectTaskCompleteDeliverableDraft deliverableDraft : deliverableDrafts){
//                if (deliverableDraft.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())){
//                    ProjectTaskDeliverable deliverable = JpaUtil.linq(ProjectTaskDeliverable.class).equal("docNO", deliverableDraft.getDocNO()).findOne();
//                    deliverable.setDocFile(deliverableDraft.getDocFile());
//                    projectTaskDeliverableService.update(deliverable);
//                }
//            }

            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);

//            ProjectTaskComplete taskComplete = JpaUtil.linq(ProjectTaskComplete.class).equal("TaskCode", projectTaskBO.getTaskCode()).findOne();
//
//            ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, taskComplete.getId());
            //记录审核意见
            taskExecutionLog.setAuditOpinion("1");
            taskExecutionLog.setAuditOpinionDesc("完工申请审核通过");
            taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
            taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
            taskExecutionLog.setAuditTime(new Date());
            taskExecutionLog.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
            projectTaskExecutionLogService.update(taskExecutionLog);

            //计算项目进度
            List<ProjectTask> tasks = this.list(ProjectTask.class, Criteria.create().addCriterion("proCode", Operator.EQ, projectTask.getProCode()));
            int size = 0;
            int finished = 0;
            for (ProjectTask task : tasks) {
                if (task.getTaskType().equals("10") && !task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.CLOSED.getCode())) {//只计算项目任务的进度
                    size += 1;

                    if (task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())) {
                        finished += 1;
                    }
                }
            }
            ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, projectTask.getProCode());
            BigDecimal progress = new BigDecimal(finished).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
            projectInfo.setSchedule(progress);
            projectInfoService.update(projectInfo);
            //任务交付物审核结束
            List<ProjectTaskCompleteDeliverableDraft> list = projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTaskBO.getTaskCode()));
            for (ProjectTaskCompleteDeliverableDraft projectTaskCompleteDeliverableDraft : list) {
                projectTaskCompleteDeliverableDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
                projectTaskCompleteDeliverableDraftService.update(projectTaskCompleteDeliverableDraft);
            }

            //审核不通过
        } else if (projectTaskBO.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode())) {
            ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());
            ProjectTask projectTask = this.getById(ProjectTask.class, projectTaskBO.getTaskCode());
            String executionStatus = projectTask.getExecutionStatus();
            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);

//            //修改申请单为关闭
//            ProjectTaskComplete taskComplete = JpaUtil.linq(ProjectTaskComplete.class).equal("TaskCode", projectTaskBO.getTaskCode()).findOne();
//            taskComplete.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
//            projectTaskCompleteService.update(taskComplete);

            //记录审核意见
            taskExecutionLog.setAuditOpinion("0");
            taskExecutionLog.setAuditOpinionDesc("完工申请审核未通过");
            taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
            taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
            taskExecutionLog.setAuditTime(new Date());
            projectTaskExecutionLogService.update(taskExecutionLog);
            //任务交付物审核结束
            List<ProjectTaskCompleteDeliverableDraft> list = projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTaskBO.getTaskCode()));
            for (ProjectTaskCompleteDeliverableDraft projectTaskCompleteDeliverableDraft : list) {
                projectTaskCompleteDeliverableDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
                projectTaskCompleteDeliverableDraftService.update(projectTaskCompleteDeliverableDraft);
            }
//            //删除当前任务完工申请单
//            JpaUtil.lind(ProjectTaskComplete.class).equal("taskCode", projectTaskComplete.getTaskCode()).delete();
//            //删除任务交付物
//            JpaUtil.lind(ProjectTaskCompleteDeliverableDraft.class).equal("taskCode", projectTaskComplete.getTaskCode()).delete();
            return Result.OK("完工申请审核未通过");
        }
        return Result.OK("完工申请审核成功");
    }

    @Override
    @Transactional
    public Result<?> finishAuditWork(String key, String loginUsername, String businessKey, Map<String, Object> properties) {
        String taskCode = properties.get("taskCode").toString();
        ProjectTask byId = this.getById(ProjectTask.class, taskCode);
        //判断前置任务
        String beforeTask = byId.getBeforeTask();
        if (beforeTask !=null && !beforeTask.equals("")){
            //开始-完成
            if (byId.getTaskLink().equals(PlmEnums.TaskLink.START_END.getCode())){
                ProjectTask byId1= this.getById(ProjectTask.class, beforeTask);
                if (byId1.getExecutionStatus().equals(PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode())){
                    throw new MBootException("前置任务未开始，当前任务不允许完工");
                }
            }
            //完成-完成
            if (byId.getTaskLink().equals(PlmEnums.TaskLink.END_END.getCode())){
                ProjectTask byId1 = this.getById(ProjectTask.class, beforeTask);
                if (!byId1.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())){
                    throw new MBootException("前置任务未完工，当前任务不允许完工");
                }
            }
        }
        if(byId == null) {
            return Result.error("任务不存在！");
        }

        // 判断任务状态是否允许执行
        if(!PlmEnums.ExecutionStatus.EXECUTING.getCode().equals(byId.getExecutionStatus())) {
            return Result.error("任务状态不允许执行完工申请！");
        }


        // 检查进度值是否有效
        BigDecimal progress = new BigDecimal(properties.get("progress").toString());
        if (progress.compareTo(byId.getProgress()) < 0
                || progress.compareTo(BigDecimal.valueOf(100)) > 0) {
            return Result.error("进度更新无效：不可低于当前进度且不可超过100%");
        }

        //校验子任务是否已完成
        List<ProjectTask> childTasks = JpaUtil.linq(ProjectTask.class)
                .equal("parentTaskCode", taskCode)
                .in("executionStatus", PlmEnums.ExecutionStatus.WAIT_FOR_START.getCode(), PlmEnums.ExecutionStatus.EXECUTING.getCode())
                .list();
        if (!childTasks.isEmpty()) {
            String taskCodes = childTasks.stream().map(ProjectTask::getTaskCode).collect(Collectors.joining(","));
            return Result.error(String.format("子任务[%s]未完成，请先处理子任务！", taskCodes));
        }
//        String bpmnStatus = properties.get("bpmnStatus").toString();
//        if (bpmnStatus == null) {
//            if (!bpmnStatus.equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode()) &&
//                    !bpmnStatus.equals(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode())) {
//                List<ProjectTaskComplete> completes = projectTaskCompleteService.list(ProjectTaskComplete.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTaskBO.getTaskCode()));
//                {
//                    for (ProjectTaskComplete taskComplete : completes) {
//                        if (taskComplete.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())) {
//                            return Result.error("有未完成的审核，请勿重复提交！");
//                        }
//                    }
//                }
//            }
//        }
        //校验当前任务是否存在审核中的完工申请
        if(!checkApplyTask(byId)){
            String taskHead = getThePersonInChargeOfTheAudit(byId);
            return Result.error("当前任务存在未完成的申请，请先审核！"+"\n"+
                    "任务编码："+byId.getTaskCode()+"\n"+
                    "任务名称："+byId.getTaskName()+"\n"+
                    "任务审核人："+taskHead);
        }
//        if (bpmnStatus == null) {
            //记录log
            ProjectTask projectTask = this.getById(ProjectTask.class, taskCode);
            ProjectTaskExecutionLog executionLog = new ProjectTaskExecutionLog();
            BeanUtil.copyProperties(byId, executionLog, "crudType", "saveTransient","deliverables");

            executionLog.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());//判断是否是工作流的
            executionLog.setTaskCode(projectTask.getTaskCode());
            executionLog.setLogType(PlmEnums.LogType.COMPLETEWORKFLOW.getCode());
            executionLog.setApplicant(SecurityUtils.getLoginUsername());
            executionLog.setApplyTime(new Date());
            executionLog.setOriProgress(projectTask.getProgress());
            executionLog.setApplyDesc(properties.get("applyDesc") !=null ? properties.get("applyDesc").toString():null);//说明
            executionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
            executionLog.setHead(getTaskHead(projectTask));
            executionLog.setHeadTask(projectTask.getHead());
            executionLog.setProCode(projectTask.getProCode());
            executionLog.setActualStartTime(Invert(properties.get("actualStartTime").toString()));//实际开始日期 //string类型转化为Date类型
            executionLog.setActualEndTime(Invert(properties.get("actualEndTime").toString()));//实际结束日期 //string类型转化为Date类型
            executionLog.setActualDuration(properties.get("actualDuration")!=null ?new BigDecimal(properties.get("actualDuration").toString()):null);//实际工期（天）
            executionLog.setNormalWorkTime(properties.get("normalWorkTime")!=null ? new BigDecimal(properties.get("normalWorkTime").toString()):null);//正常工时
            executionLog.setOvertimeWorkTime(properties.get("overtimeWorkTime")!=null ?new BigDecimal(properties.get("overtimeWorkTime").toString()):null);//加班工时
            executionLog.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());//审批状态
            JpaUtil.save(executionLog);
            String id = executionLog.getId();
            properties.put("taskLogId", id);
        //发起工作流
            ProcessInstance processInstance = bpmnFlowService.startWithFormByKey(key, loginUsername, id, properties);
        executionLog.setProcessInstanceId(processInstance.getId());
        JpaUtil.update(executionLog);

        //存入项目任务-审核记录
        ProjectTaskAuditRecords records = new ProjectTaskAuditRecords();
        records.setTaskLogId(executionLog.getId());
        records.setTaskCode(projectTask.getTaskCode());
        records.setProCode(projectTask.getProCode());
        records.setOperationalNodes("30");//完工
        records.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
        records.setApplyTime(new Date());
        records.setApplicant(SecurityUtils.getLoginUsername());
        records.setReason(executionLog.getApplyDesc());
        records.setProcessInstanceId(processInstance.getId());
        projectTaskAuditRecordsService.save(records);
//            ProjectTaskComplete taskComplete = new ProjectTaskComplete();
//            BeanUtil.copyProperties(byId, taskComplete, "crudType", "saveTransient","deliverables");
//            BeanUtil.copyProperties(projectTaskComplete, taskComplete, "crudType", "saveTransient","deliverables");
//            taskComplete.setApplicant(SecurityUtils.getLoginUsername());
//            taskComplete.setApplyTime(new Date());
//            taskComplete.setBpmnStatus(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode());
////            taskComplete.setId(executionLog.getId());
//            taskComplete.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());//是否审核结束 1是 0否
//            taskComplete.setWorkflowId(projectTaskComplete.getWorkflowId());
//            projectTaskCompleteService.save(taskComplete);

//            projectTask.setWorkflowId(projectTaskComplete.getWorkflowId());//存入申请单的ID
//            this.update(projectTask);
            //存交付物进任务交付物模板
            List<LinkedHashMap<String, Object>> deliverables = (List<LinkedHashMap<String, Object>>) properties.get("deliverables");
            if (deliverables != null) {
                for (LinkedHashMap<String, Object> map : deliverables){
                    ProjectTaskCompleteDeliverableDraft draft = new ProjectTaskCompleteDeliverableDraft();
                    draft.setTaskLogId(executionLog.getId());
                    draft.setDocNO(map.get("docNO").toString());
                    draft.setTaskCode(map.get("taskCode").toString());
                    draft.setDocName(map.get("docName").toString());
                    draft.setDocFile(map.get("docFile").toString());
                    draft.setDocTemp(map.get("docTemp") !=null ? map.get("docTemp").toString():null);
                    draft.setDocType(map.get("docType").toString());
                    draft.setNumber(map.get("number")!=null ?Integer.valueOf(map.get("number").toString()):null);
//                    BeanUtil.copyProperties(deliverable, draft, "crudType", "saveTransient", "id");
                    draft.setIsAuditEnd(CommonEnums.YesNo.NO.getCode());
                    projectTaskCompleteDeliverableDraftService.save(draft);
                }
            }
            return Result.OK(executionLog);
//        }
//        return null;
    }

    /**
     * string类型转化为Date类型
     * @param dateStr
     * @return
     */
    private Date Invert(String dateStr) {
        if (dateStr != null) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate date = LocalDate.parse(dateStr, formatter);
            Date oldDate = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
            return oldDate;
        }
        return null;
    }

    @Override
    @Transactional
    public Result<?> finishAuditWorkOK(ProjectTaskBO projectTaskBO) {
        //当审核通过时
        if (projectTaskBO.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
            ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());

            ProjectTask projectTask = this.getById(ProjectTask.class, projectTaskBO.getTaskCode());
//            //更改该申请单
//            ProjectTaskComplete taskComplete = JpaUtil.linq(ProjectTaskComplete.class).equal("taskCode", projectTaskBO.getTaskCode()).findOne();
//            taskComplete.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
//            projectTaskCompleteService.update(taskComplete);

            String executionStatus = projectTask.getExecutionStatus();
            projectTask.setExecutionStatus(PlmEnums.ExecutionStatus.FINISHED.getCode());
            projectTask.setNormalWorkTime(taskExecutionLog.getNormalWorkTime() !=null ? taskExecutionLog.getNormalWorkTime():null);
            projectTask.setOvertimeWorkTime(taskExecutionLog.getOvertimeWorkTime()!=null ? taskExecutionLog.getOvertimeWorkTime():null);
            projectTask.setActualDuration(taskExecutionLog.getActualDuration()!=null ?taskExecutionLog.getActualDuration():null);
            projectTask.setActualEndTime(taskExecutionLog.getActualEndTime());
            projectTask.setActualStartTime(taskExecutionLog.getActualStartTime());
            projectTask.setProgress(new BigDecimal("100"));
            this.update(projectTask);
//            //回写交付物
//            List<ProjectTaskCompleteDeliverableDraft> deliverableDrafts= projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode",Operator.EQ, projectTaskComplete.getTaskCode()));
//            for (ProjectTaskCompleteDeliverableDraft deliverableDraft : deliverableDrafts){
//                if (deliverableDraft.getIsAuditEnd().equals(CommonEnums.YesNo.NO.getCode())){
//                    ProjectTaskDeliverable deliverable = JpaUtil.linq(ProjectTaskDeliverable.class).equal("docNO", deliverableDraft.getDocNO()).findOne();
//                    deliverable.setDocFile(deliverableDraft.getDocFile());
//                    projectTaskDeliverableService.update(deliverable);
//                }
//            }

            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);

//            ProjectTaskComplete taskComplete = JpaUtil.linq(ProjectTaskComplete.class).equal("TaskCode", projectTaskBO.getTaskCode()).findOne();
//
//            ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, taskComplete.getId());
            //记录审核意见
            taskExecutionLog.setAuditOpinion("1");
            taskExecutionLog.setAuditOpinionDesc("完工申请审核通过");
            taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode());
            taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
            taskExecutionLog.setAuditTime(new Date());
            taskExecutionLog.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());
            projectTaskExecutionLogService.update(taskExecutionLog);

            //存入项目任务-审核记录
            ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", taskExecutionLog.getId()).findOne();
            one.setBpmnStatus(projectTaskBO.getBpmnStatus());
            one.setAuditTime(new Date());
            projectTaskAuditRecordsService.update(one);

            //计算项目进度
            List<ProjectTask> tasks = this.list(ProjectTask.class, Criteria.create().addCriterion("proCode", Operator.EQ, projectTask.getProCode()));
            int size = 0;
            int finished = 0;
            for (ProjectTask task : tasks) {
                if (task.getTaskType().equals("10") && !task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.CLOSED.getCode())) {//只计算项目任务的进度
                    size += 1;

                    if (task.getExecutionStatus().equals(PlmEnums.ExecutionStatus.FINISHED.getCode())) {
                        finished += 1;
                    }
                }
            }
            ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, projectTask.getProCode());
            BigDecimal progress = new BigDecimal(finished).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
            projectInfo.setSchedule(progress);
            projectInfoService.update(projectInfo);
            //任务交付物审核结束
            List<ProjectTaskCompleteDeliverableDraft> list = projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTaskBO.getTaskCode()));
            for (ProjectTaskCompleteDeliverableDraft projectTaskCompleteDeliverableDraft : list) {
                projectTaskCompleteDeliverableDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
                projectTaskCompleteDeliverableDraftService.update(projectTaskCompleteDeliverableDraft);
            }

            //审核不通过
        } else if (projectTaskBO.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode())) {
            ProjectTaskExecutionLog taskExecutionLog = projectTaskExecutionLogService.getById(ProjectTaskExecutionLog.class, projectTaskBO.getTaskLogId());
            ProjectTask projectTask = this.getById(ProjectTask.class, projectTaskBO.getTaskCode());
            String executionStatus = projectTask.getExecutionStatus();
            //记录状态历史
            projectTaskStatusHistoryService.record(projectTask, executionStatus);

//            //修改申请单为关闭
//            ProjectTaskComplete taskComplete = JpaUtil.linq(ProjectTaskComplete.class).equal("TaskCode", projectTaskBO.getTaskCode()).findOne();
//            taskComplete.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
//            projectTaskCompleteService.update(taskComplete);

            //记录审核意见
            taskExecutionLog.setAuditOpinion("0");
            taskExecutionLog.setAuditOpinionDesc("完工申请审核未通过");
            taskExecutionLog.setAuditStatus(OrderStatusEnums.BpmnStatus.CLOSED.getStatusCode());
            taskExecutionLog.setAuditPerson(SecurityUtils.getLoginUsername());
            taskExecutionLog.setAuditTime(new Date());
            projectTaskExecutionLogService.update(taskExecutionLog);

            //存入项目任务-审核记录
            ProjectTaskAuditRecords one = JpaUtil.linq(ProjectTaskAuditRecords.class).equal("taskLogId", taskExecutionLog.getId()).findOne();
            one.setBpmnStatus("不同意");
            one.setAuditTime(new Date());
            projectTaskAuditRecordsService.update(one);

            //任务交付物审核结束
            List<ProjectTaskCompleteDeliverableDraft> list = projectTaskCompleteDeliverableDraftService.list(ProjectTaskCompleteDeliverableDraft.class, Criteria.create().addCriterion("taskCode", Operator.EQ, projectTaskBO.getTaskCode()));
            for (ProjectTaskCompleteDeliverableDraft projectTaskCompleteDeliverableDraft : list) {
                projectTaskCompleteDeliverableDraft.setIsAuditEnd(CommonEnums.YesNo.YES.getCode());//是否审核结束 1是 0否
                projectTaskCompleteDeliverableDraftService.update(projectTaskCompleteDeliverableDraft);
            }
//            //删除当前任务完工申请单
//            JpaUtil.lind(ProjectTaskComplete.class).equal("taskCode", projectTaskComplete.getTaskCode()).delete();
//            //删除任务交付物
//            JpaUtil.lind(ProjectTaskCompleteDeliverableDraft.class).equal("taskCode", projectTaskComplete.getTaskCode()).delete();
            return Result.OK("完工申请审核未通过");
        }
        return Result.OK("完工申请审核成功");
    }

    /**
     * 获取父任务负责人或项目负责人
     * @param projectTask
     * @return
     */
    private String getTaskHead(ProjectTask projectTask){
        String parentTaskCode = projectTask.getParentTaskCode();
        if(StrUtil.isNotEmpty(parentTaskCode)){
            ProjectTask parentTask = this.getById(ProjectTask.class, parentTaskCode);
            if(parentTask != null && StrUtil.isNotEmpty(parentTask.getHead())){
                return parentTask.getHead();
            }
        }
        //没有父任务获取项目负责人
        ProjectInfo projectInfo = projectInfoService.getById(ProjectInfo.class, projectTask.getProCode());
        return dealUserName(projectInfo.getProLeader());
    }
}
